package org.hackystat.projecttrajectory.resource.summary;

import java.io.StringWriter;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import javax.xml.datatype.XMLGregorianCalendar;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.hackystat.dailyprojectdata.client.DailyProjectDataClient;
import org.hackystat.projecttrajectory.resource.ProjectSummaryFactory;
import org.hackystat.projecttrajectory.resource.ProjectTrajectoryResource;
import org.hackystat.projecttrajectory.resource.summary.jaxb.ProjectSummary;
import org.hackystat.sensorbase.client.SensorBaseClient;
import org.hackystat.utilities.stacktrace.StackTrace;
import org.hackystat.utilities.tstamp.Tstamp;
import org.restlet.Context;
import org.restlet.data.MediaType;
import org.restlet.data.Request;
import org.restlet.data.Response;
import org.restlet.resource.Representation;
import org.restlet.resource.Variant;
import org.w3c.dom.Document;

/**
 * Implements the Resource for processing GET {host}/summary/{user}/{project}
 * requests to obtain a summary of the given project for the given user.
 * 
 * @author Cam Moore
 * 
 */
public class SummaryResource extends ProjectTrajectoryResource {

  /**
   * The standard constructor.
   * 
   * @param context The context.
   * @param request The request object.
   * @param response The response object.
   */
  public SummaryResource(Context context, Request request, Response response) {
    super(context, request, response);
  }

  /**
   * 
   * @param variant The representational variant requested.
   * @return The representation.
   * @see org.hackystat.projecttrajectory.resource.ProjectTrajectoryResource#getRepresentation
   */
  @Override
  public Representation getRepresentation(Variant variant) {
    if (variant.getMediaType().equals(MediaType.TEXT_XML)) {
      try {
        SensorBaseClient sbClient = super.getSensorBaseClient();
        DailyProjectDataClient dpdClient = super.getDailyProjectDataClient();
        ProjectSummaryFactory factory = 
          new ProjectSummaryFactory(this.uriUser, sbClient, dpdClient);
        XMLGregorianCalendar date;
        if (this.timestamp == null) {
           date = Tstamp.makeTimestamp();
        } 
        else {
          date = Tstamp.makeTimestamp(this.timestamp);
        }
        ProjectSummary summary = factory.getSummary(this.project, date);
        String xmlData = makeProjectSummaryString(summary);
        return super.getStringRepresentation(xmlData);
      } catch (Exception e) {
        server.getLogger().warning("Error processing project summary: " + StackTrace.toString(e));
        return null;
      }
    }
    return null;
  }

  /**
   * Returns the passed ProjectSummary instance as a String encoding of its XML
   * representation.
   * 
   * @param summary the ProjectSummary instance.
   * @return The XML String representation.
   * @throws Exception If problems occur during translation.
   */
  private String makeProjectSummaryString(ProjectSummary summary) throws Exception {
    JAXBContext summaryJAXB = (JAXBContext) this.server.getContext().getAttributes().get(
        "SummaryJAXB");
    Marshaller marshaller = summaryJAXB.createMarshaller();
    DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
    dbf.setNamespaceAware(true);
    DocumentBuilder documentBuilder = dbf.newDocumentBuilder();
    Document doc = documentBuilder.newDocument();
    marshaller.marshal(summary, doc);
    DOMSource domSource = new DOMSource(doc);
    StringWriter writer = new StringWriter();
    StreamResult result = new StreamResult(writer);
    TransformerFactory tf = TransformerFactory.newInstance();
    Transformer transformer = tf.newTransformer();
    transformer.transform(domSource, result);
    return writer.toString();
  }
}
